#include <stdio.h>
#include "type.h"
#include "err.h"

#define PTR_1(mat) {\
	p0##mat = malloc((mat->height)<<2);\
	p0##mat[0] = mat->data.ptr;\
	for(i=1;i<mat->height;i++)\
		p0##mat[i] = p0##mat[i-1]+mat->width;\
}\

#define PTR_3(mat) {\
	p0##mat = malloc((mat->height)<<2);\
	p0##mat[0] = mat->data.ptr;\
	for(i=1;i<mat->height;i++)\
		p0##mat[i] = p0##mat[i-1]+mat->width;\
	p1##mat = malloc((mat->height)<<2);\
	for(i=0;i<mat->height;i++)\
		p1##mat[i] = p0##mat[i]+mat->size;\
	p2##mat = malloc((mat->height)<<2);\
	for(i=0;i<mat->height;i++)\
		p2##mat[i] = p1##mat[i]+mat->size;\
}\

#define PTR_4(mat) {\
	p0##mat = malloc((mat->height)<<2);\
	p0##mat[0] = mat->data.ptr;\
	for(i=1;i<mat->height;i++)\
		p0##mat[i] = p0##mat[i-1]+mat->width;\
	p1##mat = malloc((mat->height)<<2);\
	for(i=0;i<mat->height;i++)\
		p1##mat[i] = p0##mat[i]+mat->size;\
	p2##mat = malloc((mat->height)<<2);\
	for(i=0;i<mat->height;i++)\
		p2##mat[i] = p1##mat[i]+mat->size;\
	p3##mat = malloc((mat->height)<<2);\
	for(i=0;i<mat->height;i++)\
		p3##mat[i] = p2##mat[i]+mat->size;\
}\


#define SRC_0(x,y) *(p0src[y]+(x))
#define DST_0(x,y) *(p0dst[y]+(x))
#define SRC_1(x,y) *(p1src[y]+(x))
#define DST_1(x,y) *(p1dst[y]+(x))
#define SRC_2(x,y) *(p2src[y]+(x))
#define DST_2(x,y) *(p2dst[y]+(x))
#define SRC_3(x,y) *(p3src[y]+(x))
#define DST_3(x,y) *(p3dst[y]+(x))
#define FLAG(x,y) *(p0flag[y]+(x))

#define ABS(x) (((x)>0)?(x):(0-(x)))

ImgMat *imgCreateMat(int height,int width,char type);

void imgFill(ImgMat *src,ImgMat *dst,ImgLocate *start_locate,int replace_gray,int thresh)
{
	#ifdef DEBUG
	SOURCE_ERROR_CHECK(imgFill,src);
	DESTINATION_ERROR_CHECK(imgFill,dst);
	#endif
	
	int cn;
	cn = ((src->type&0xF8)>>3)+1;
	
	#ifdef DEBUG
	if(cn!=1)
		IMG_ERR(imgFill,"number of mat channel is not correct"); 
	if(thresh<0)
		IMG_ERR(imgFill,"thresh is less than 0");
	#endif
	
	int img_width;
	img_width = src->width;
	
	int img_height;
	img_height = src->height;
	
	if((src->height != dst->height)||(src->width != dst->width)||(dst->type != TYPE_8UC1))
		imgMatRedefine(dst,src->height,src->width,TYPE_8UC1);
	
	imgCopyMat(src,dst);
	
	ImgMat *flag;
	flag = imgCreateMat(img_height,img_width,TYPE_8UC1);
	imgCleanMat(flag);
	
	int i,j;
	
	unsigned char **p0src;
	PTR_1(src);
	
	unsigned char **p0dst;
	PTR_1(dst);
	
	unsigned char **p0flag;
	PTR_1(flag);
	
	int start_x;
	start_x = start_locate->x;
	
	int start_y;
	start_y = start_locate->y;
	
	int mark1,mark2;
	
	FLAG(start_x,start_y) = 255;
	DST_0(start_x,start_y) = replace_gray;
	
	printf("aaaaaaaaaaaaaaaaaaaa(%d,%d)\n",start_x,start_y);
	printf("replace_gray is %d\n",replace_gray);
	printf("thresh is %d\n",thresh);
	printf("DST_0(30,30) is %d\n",DST_0(30,30));
	printf("FLAG(30,30) is %d\n",FLAG(30,30));
	
	for(i=start_x+1;i<img_width;i++)
	{
		if(FLAG(i-1,start_y)==255)
		{			
			if(ABS(SRC_0(i,start_y)-SRC_0(i-1,start_y))<thresh)
			{
				FLAG(i,start_y) = 255;
				DST_0(i,start_y) = replace_gray;
			}
		}
		else
			break;
	}
	for(i=start_x-1;i>=0;i--)
	{
		if(FLAG(i+1,start_y) == 255)
			if(ABS(SRC_0(i,start_y)-SRC_0(i+1,start_y))<thresh)
			{
				FLAG(i,start_y) = 255;
				DST_0(i,start_y) = replace_gray;
			}
		else
			break;
	}
	
	printf("DST_0(0,30) is %d\n",DST_0(0,30));
	

	
replace:
	mark2 = 0;
	for(j=start_y+1;j<img_height;j++)
	{
		mark1 = 0;
		
		if(FLAG(0,j)==255)
			mark1 = 1;
		if((FLAG(0,j-1)==255)&&(ABS(SRC_0(0,j)-SRC_0(0,j-1))<thresh))
		{
			FLAG(0,j) = 255;
			DST_0(0,j) = replace_gray;
			mark1 = 1;
			mark2 = 1;
		}
		else if((FLAG(1,j)==255)&&(ABS(SRC_0(0,j)-SRC_0(1,j))<thresh))
		{
			FLAG(0,j) = 255;
			DST_0(0,j) = replace_gray;
			mark1 = 1;
			mark2 = 1;
		}
				
		for(i=1;i<img_width;i++)
		{
			if(FLAG(i,j) == 255)
			{
				mark1 = 1;
				continue;
			}
			
			if(FLAG(i-1,j)==255)
				if(ABS(SRC_0(i,j)-SRC_0(i-1,j))<thresh)
				{
					FLAG(i,j) = 255;
					DST_0(i,j) = replace_gray;
					mark1 = 1;
					mark2 = 1;
					continue;
				}

			if(FLAG(i,j-1)==255)
				if(ABS(SRC_0(i,j)-SRC_0(i,j-1))<thresh)
				{
					FLAG(i,j) = 255;
					DST_0(i,j) = replace_gray;
					mark1 = 1;
					mark2 = 1;
					continue;
				}
		}
		
		if(mark1 == 0)
			break;
	}
	
		
	start_y = j-1;
	
	for(j=start_y-1;j>=0;j--)
	{
		mark1 = 0;
		
		if(FLAG(0,j)==255)
			mark1 = 1;
		else if((FLAG(0,j+1)==255)&&(ABS(SRC_0(0,j)-SRC_0(0,j+1))<thresh))
		{
			FLAG(0,j) = 255;
			DST_0(0,j) = replace_gray;
			mark1 = 1;
			mark2 = 1;
		}
		else if((FLAG(1,j)==255)&&(ABS(SRC_0(0,j)-SRC_0(1,j))<thresh))
		{
			FLAG(0,j) = 255;
			DST_0(0,j) = replace_gray;
			mark1 = 1;
			mark2 = 1;
		}
				
		for(i=1;i<img_width;i++)
		{
			if(FLAG(i,j) == 255)
			{
				mark1 = 1;
				continue;
			}
			
			if(FLAG(i-1,j)==255)
				if(ABS(SRC_0(i,j)-SRC_0(i-1,j))<thresh)
				{
					FLAG(i,j) = 255;
					DST_0(i,j) = replace_gray;
					mark1 = 1;
					mark2 = 1;
					continue;
				}

			if(FLAG(i,j+1)==255)
				if(ABS(SRC_0(i,j)-SRC_0(i,j+1))<thresh)
				{
					FLAG(i,j) = 255;
					DST_0(i,j) = replace_gray;
					mark1 = 1;
					mark2 = 1;
					continue;
				}
		}
		
		if(mark1 == 0)
			break;
	}
	// return;
	if(mark2==1)
		goto replace;
	
	imgReleaseMat(flag);
}
			
void Fill(ImgMat *src,ImgMat *dst,ImgLocate *start_locate,int replace_gray,int thresh)
{		
	#ifdef DEBUG
	SOURCE_ERROR_CHECK(imgFill,src);
	#endif
	
	if(dst==NULL)
	{
		printf("aaaaaaaaaaaaa\n");
		dst = imgCreateMat(src->height,src->width,src->type);
		imgFill(src,dst,start_locate,replace_gray,thresh);
		free(src->data.ptr);
		free(src->hidinfo);
		*src = *dst;
		free(dst);
	}
	else
		imgFill(src,dst,start_locate,replace_gray,thresh);
}
			
			
			